#include "CAN.h"
/*****************************************************************************
 *
 * Microchip DeviceNet Stack (CAN Driver Source)
 *
 *****************************************************************************
 * FileName:        CAN.c
 * Dependencies:
 * Processor:       PIC18F with CAN
 * Compiler:        C18 02.20.00 or higher
 * Linker:          MPLINK 03.40.00 or higher
 * Company:         Microchip Technology Incorporated
 *
 * Software License Agreement
 *
 * The software supplied herewith by Microchip Technology Incorporated
 * (the "Company") is intended and supplied to you, the Company's
 * customer, for use solely and exclusively with products manufactured
 * by the Company.
 *
 * The software is owned by the Company and/or its supplier, and is
 * protected under applicable copyright laws. All rights are reserved.
 * Any use in violation of the foregoing restrictions may subject the
 * user to criminal sanctions under applicable laws, as well as to
 * civil liability for the breach of the terms and conditions of this
 * license.
 *
 * THIS SOFTWARE IS PROVIDED IN AN "AS IS" CONDITION. NO WARRANTIES,
 * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
 * TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
 * IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
 * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
 *
 *
 *  This version of the CAN driver for DeviceNet is designed to be very
 *  simple. Filtering options are static and limited. Receive buffering is
 *  is restricted to only the two hardware receive buffers. And transmit
 *  buffering is restricted to only one of three transmit buffers. However,
 *  the architecture of this driver lends itself to be upgradable to achieve
 *  better performance without changes to the firmware using this driver.
 *
 *
 *
 * Author               Date        Comment
 *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 * Ross Fosler          04/28/03    ...
 *
 *****************************************************************************/

//lifeng changed for stm32F0xx 2022-08
//lifeng changed for stm32F1xx 2023-04

#include "dnetdef.h"          // Global definitions file
#include <stm32f1xx.h>


/*********************************************************************
 * Private definitions derived from Maestro Generated Definitions
 ********************************************************************/

//lifeng 2022-08
//PCLK 28MHz
//注意以下值正好是MX_CAN_Init函数中的值-1，所有值都减1
#define BTR_TSJW 1           //+1=2
#define BTR_TBS1 3           //+1=4
#define BTR_TBS2 2           //+1=3
#define BTR_500KTBRP 6       //+1=7
#define BTR_250KTBRP 13      //+1=14
#define BTR_125KTBRP 27      //+1=28

typedef union
{
    unsigned long b;
    unsigned char c[4];
}unli_l_c;

/*********************************************************************
 * Private types
 ********************************************************************/
typedef union _T_INT
{
    unsigned short word;        //lifeng 2022-08
    struct _BYTES_
    {
        unsigned char LSB;
        unsigned char MSB;
    }bytes;

}_INT;

/*// This type is used to copy all first fragment messages
typedef struct T_CAN_DATA_TYP0
{
    unsigned char   D0;
    unsigned char   D1;
    unsigned char   D2;
    unsigned char   D3;
    unsigned char   D4;
    unsigned char   D5;
    unsigned char   D6;
    unsigned char   D7;
}_CAN_DATA_TYP0;

// This type is used for fragmented I/O messages
typedef struct T_CAN_DATA_TYP1
{
    unsigned char   D1;
    unsigned char   D2;
    unsigned char   D3;
    unsigned char   D4;
    unsigned char   D5;
    unsigned char   D6;
    unsigned char   D7;
}_CAN_DATA_TYP1;

// This type is specifically used for fragmented explicit messages
typedef struct T_CAN_DATA_TYP2
{
    unsigned char   D2;
    unsigned char   D3;
    unsigned char   D4;
    unsigned char   D5;
    unsigned char   D6;
    unsigned char   D7;
}_CAN_DATA_TYP2;*/


 unsigned char _msgTxTag;       // Tag used to remember the last instance
 unsigned char _msgRxBuf;       // Reference to the current active rx buffer
// unsigned char _mac_filter;

//2022-09 lifeng 发送缓冲区
 union
 {
     unsigned long b[2];
     unsigned char c[8];
 }txLFbuf;

/*********************************************************************
 * Function:         unsigned char CANOpen(void)
 *
 * PreCondition:    Bitrate and filters should be setup
 *
 * Input:           void
 *
 * Output:          unsigned char status of the request
 *
 * Side Effects:
 *
 * Overview:        Open CAN communications
 *
 * Note:            This function should be interprited as a request
 *                  rather than a command. Use CANIsOpen() to
 *                  verify the bus has been opened.
 ********************************************************************/
//lifeng 2022-08

 unsigned char CANOpen(void)
{
    // Place the CAN peripherial into Normal mode
    CAN1->MCR=0x00010044;    //发送按请求顺序  非睡眠  正常模式   ABOM=1:自动离线恢复，与PIC18F458一致
    while(CAN1->MSR&0x00000001){;}         //确认正常模式
    return (1);
}

/*********************************************************************
 * Function:         unsigned char CANClose(void)
 *
 * PreCondition:    Bus communications should be open.
 *
 * Input:           void
 *
 * Output:          unsigned char status of the request
 *
 * Side Effects:
 *
 * Overview:        Close CAN communications
 *
 * Note:            This function should be interprited as a request
 *                  rather than a command. Use CANIsOpen() to
 *                  verify the bus is still open.
 ********************************************************************/
//lifeng 2022-08
 unsigned char CANClose(void)
{
    // Place the CAN peripherial into Config mode
    CAN1->MCR=0x00010045;     //发送按请求顺序  非睡眠  初始化模式   ABOM=1:自动离线恢复，与PIC18F458一致
    while(!(CAN1->MSR&0x00000001)){;}         //确认初始化模式
    return (1);
}

/*********************************************************************
 * Function:         unsigned char CANIsOpen(void)
 *
 * PreCondition:
 *
 * Input:           void
 *
 * Output:          unsigned char status of the request
 *
 * Side Effects:
 *
 * Overview:        Return the status of communication.
 *                  TRUE = Open, FALSE = Closed
 *
 * Note:
 ********************************************************************/
//lifeng 2022-08
 unsigned char CANIsOpen(void)
{
    //return (!(CANSTAT & 0xE0));
    if(CAN1->MSR&0x00000003){return 0;}
    else{return 1;}
}

/*********************************************************************
 * Function:         unsigned char CANSetFilter( unsigned int filterID)
 *
 * PreCondition:
 *
 * Input:           16-bit filterID
 *
 * Output:          unsigned char status of the request
 *
 * Side Effects:    Communication may be temporarily interrupted
 *
 * Overview:        Adds a filter to the scan list.
 *
 * Note:            No scan list is actually created in this version;
 *                  a hardware filter is to allow a CAN ID or group
 *                  of IDs to be received.
 ********************************************************************/
//lifeng 2022-08
 unsigned char CANSetFilter( unsigned short filterID)
{
    // Setup masks and filters according to the message
    unsigned long l1;
    switch (filterID&0x00E0)
    {
        case 0x0000:
            CAN1->FA1R&=0xfffffffe;          //禁止filter0
            l1=(unsigned long)filterID;
            l1=0xffe00000&(l1<<16);
            CAN1->sFilterRegister[0].FR1=l1;                 //过滤器编号n=0
            CAN1->sFilterRegister[0].FR2=0xffe00006;         //检查id10-0 IDE RTR
            CAN1->FA1R|=0x00000001;          //激活filter0
            break;

        case 0x0020:
            CAN1->FA1R&=0xfffffffd;          //禁止filter1
            l1=(unsigned long)filterID;
            l1=0xffe00000&(l1<<16);
            CAN1->sFilterRegister[1].FR1=l1;                 //过滤器编号n=1
            CAN1->sFilterRegister[1].FR2=0xffe00006;         //检查id10-0 IDE RTR
            CAN1->FA1R|=0x00000002;          //激活filter1
            break;

        case 0x0040:
        case 0x0060:
        case 0x0080:
        case 0x00A0:
        case 0x00C0:
        case 0xE0:
            CAN1->FA1R&=0xfffffffb;          //禁止filter2
            l1=(unsigned long)filterID;
            l1=0xffe00000&(l1<<16);
            CAN1->sFilterRegister[2].FR1=l1;                 //过滤器编号n=2
            CAN1->sFilterRegister[2].FR2=0xff000006;         //检查id10-3 IDE RTR
            CAN1->FA1R|=0x00000004;          //激活filter2
            break;
    }
    return (1);
}

/*********************************************************************
 * Function:         unsigned char CANClrFilter( unsigned short filterID)
 *
 * PreCondition:
 *
 * Input:           16-bit filterID
 *
 * Output:          unsigned char status of the request
 *
 * Side Effects:    Communication may be temporarily interrupted
 *
 * Overview:        Removes a filter from the scan list.
 *
 * Note:            No scan list is actually created in this version;
 *                  a hardware filter is used to allow a CAN ID or
 *                  group of IDs to be received.
 ********************************************************************/
//lifeng 2022-08

 unsigned char CANClrFilter( unsigned short filterID)
{
    //CAN1->FMR|=0x00000001;           //过滤配置模式

    // Clear filters
    switch (filterID&0x00E0)
    {
        case 0x0000:
            CAN1->FA1R&=0xfffffffe;          //禁止filter0
            break;

        case 0x0020:
            CAN1->FA1R&=0xfffffffd;          //禁止filter1
            break;

        case 0x0040:
        case 0x0060:
        case 0x0080:
        case 0x00A0:
        case 0x00C0:
        case 0x00E0:
            break;
    }

    // lifeng 2022-08
    //CAN1->FMR&=0xfffffffe;

    return (1);
}

/*********************************************************************
 * Function:         unsigned char CANSetBitRate( unsigned char bitrate)
 *
 * PreCondition:
 *
 * Input:           bitrate
 *
 * Output:          unsigned char status of the request
 *
 * Side Effects:    Communication may be temporarily interrupted
 *
 * Overview:        Changes the bitrate of the node.
 *
 * Note:
 ********************************************************************/
//lifeng 2022-08

 unsigned char CANSetBitRate( unsigned char bitrate)
{
    switch (bitrate)
    {
        case 0:
            CAN1->BTR=(BTR_TSJW<<24)|(BTR_TBS1<<20)|(BTR_TBS2<<16)|BTR_125KTBRP;
            break;
        case 1:
            CAN1->BTR=(BTR_TSJW<<24)|(BTR_TBS1<<20)|(BTR_TBS2<<16)|BTR_250KTBRP;
            break;
        case 2:
            CAN1->BTR=(BTR_TSJW<<24)|(BTR_TBS1<<20)|(BTR_TBS2<<16)|BTR_500KTBRP;
            break;
        default:
            return (0);         // This could be autobaud
    }
    return (1);
}


/*********************************************************************
 * Function:         unsigned char CANIsBusError(void)
 *
 * PreCondition:
 *
 * Input:           none
 *
 * Output:          unsigned char status of the request
 *
 * Side Effects:
 *
 * Overview:        Returns an error code.
 *
 * Note:
 ********************************************************************/
//lifeng 2022-08
 unsigned char CANIsBusOffError(void)
{
    // If there is an error then return the Bus-off flag
    unsigned char te1;
    if(CAN1->ESR&0x00000007)
    {
        // Reset the interrupt flag
        if(CAN1->ESR&0x00000004){te1=1;}
        else{te1=0;}

        CAN1->MSR&=0xfffffffb;

        // Return the bus off bit
        return te1;
    }
    // Otherwise return no error
    else
        return (0);
}



/*********************************************************************
 * Function:         unsigned char CANIsRxRdy(void)
 *
 * PreCondition:
 *
 * Input:           none
 *
 * Output:          unsigned char status of the request
 *
 * Side Effects:
 *
 * Overview:        Returns TRUE if there is data waiting.
 *
 * Note:
 ********************************************************************/
//lifeng 2022-08
 unsigned char CANIsRxRdy(void)
{
    // Check hardware buffer 0
    if (CAN1->RF0R&0x00000003)
    {
        _msgRxBuf = 0;
        return 1;
    }
    else

    // Check hardware buffer 1
    if (CAN1->RF1R&0x00000003)
    {
        _msgRxBuf = 1;
        return 1;
    }
    else
        return 0;
}

/*********************************************************************
 * Function:        void CANRead(void)
 *
 * PreCondition:
 *
 * Input:           none
 *
 * Output:          none
 *
 * Side Effects:
 *
 * Overview:        Indicates to the module that the data has been read.
 *
 * Note:            This effectively frees the active hardware buffer
 *                  to continue receiving.
 ********************************************************************/
//lifeng 2022-08
void CANRead(void)
{
    if (_msgRxBuf == 0)
    {
        CAN1->RF0R|=0x00000020;
    }
    else
    if (_msgRxBuf == 1)
    {
        CAN1->RF1R|=0x00000020;
    }
}

/*********************************************************************
 * Function:         unsigned char CANIsTxRdy(void)
 *
 * PreCondition:
 *
 * Input:           none
 *
 * Output:          unsigned char status of the request
 *
 * Side Effects:
 *
 * Overview:        Returns TRUE if the transmit engine is ready to
 *                  accept new data to transmit.
 *
 * Note:            This function is as simple as it gets, i.e. direct
 *                  access to only one TX buffer.
 ********************************************************************/
//lifeng 2022-08
 unsigned char CANIsTxRdy(void)
{
    if(CAN1->TSR&0x04000000){return 1;}            //只使用发送邮箱0
    else{return 0;}
}

/*********************************************************************
 * Function:         unsigned char CANIsMsgSent(void)
 *
 * PreCondition:
 *
 * Input:           none
 *
 * Output:          unsigned char status of the request
 *
 * Side Effects:
 *
 * Overview:        Returns the tag of the data that was last transmitted.
 *                  Any additional calls without additional transmissions
 *                  will return NULL.
 *
 * Note:            This is useful to determine when and who's data was
 *                  placed on the bus. This may seem redundent since
 *                  only one hardware buffer is used; however, this
 *                  architecture allows for expansion to deep software/
 *                  hardware buffer designs without major changes to
 *                  the upper level firmware.
 ********************************************************************/
//lifeng 2022-08
 unsigned char CANIsMsgSent(void)
{
     unsigned char temp;

    if(CAN1->TSR&0x00000001)
    {
        //CAN1->TSR|=0x00000001;
        temp = _msgTxTag;
        _msgTxTag = 0;
        return (temp);
    }
    else
        return (0);
}

/*********************************************************************
 * Function:        void CANSend( unsigned char txTag)
 *
 * PreCondition:
 *
 * Input:           none
 *
 * Output:          none
 *
 * Side Effects:
 *
 * Overview:        Tell the transmit engine that the loaded data is
 *                  is ready to send.
 *
 * Note:            Data may not be sent immediately. The tag is used
 *                  to trace the transmission since other data may
 *                  also be queued to transmit.
 ********************************************************************/
//lifeng 2022-08  加入缓冲区操作
void CANSend( unsigned char txTag)
{
    CAN1->sTxMailBox[0].TDLR=txLFbuf.b[0];
    CAN1->sTxMailBox[0].TDHR=txLFbuf.b[1];
    // Remember the message that was sent
    _msgTxTag = txTag;

    CAN1->sTxMailBox[0].TIR|=0x00000001;
}

/*********************************************************************
 * Function:         unsigned int CANGetRxCID(void)
 *
 * PreCondition:
 *
 * Input:           none
 *
 * Output:          unsigned int connection ID (11-bit CAN ID)
 *
 * Side Effects:
 *
 * Overview:        Get the connection ID from the current receive
 *                  message.
 *
 * Note:            The CAN ID is assumed to be left justified within
 *                  the 16-bit word.
 ********************************************************************/
//lifeng 2022-08
 unsigned int CANGetRxCID(void)
{
     _INT cid;
    unsigned char te1;

    if (_msgRxBuf == 0)
    {
        te1=(unsigned char)((CAN1->sFIFOMailBox[0].RIR>>16)&0x000000e0);
        if(CAN1->sFIFOMailBox[0].RIR&0x00000002){te1|=0x10;}
        if(CAN1->sFIFOMailBox[0].RIR&0x00000004){te1|=0x08;}
        cid.bytes.LSB = te1;
        te1=(unsigned char)((CAN1->sFIFOMailBox[0].RIR>>24)&0x000000ff);
        cid.bytes.MSB = te1;
    }
    else //if (_msgRxBuf == 1)
    {
        te1=(unsigned char)((CAN1->sFIFOMailBox[1].RIR>>16)&0x000000e0);
        if(CAN1->sFIFOMailBox[1].RIR&0x00000002){te1|=0x10;}
        if(CAN1->sFIFOMailBox[1].RIR&0x00000004){te1|=0x08;}
        cid.bytes.LSB = te1;
        te1=(unsigned char)((CAN1->sFIFOMailBox[1].RIR>>24)&0x000000ff);
        cid.bytes.MSB = te1;
    }

    return (cid.word);
}

/*********************************************************************
 * Function:         unsigned char CANGetRxCnt(void)
 *
 * PreCondition:    Data should have been received prior to calling
 *                  this function; otherwise, it is likely the returned
 *                  count is either not valid or associated to the
 *                  previous message. Use CANIsRxRdy() to determine if
 *                  data is available.
 *
 * Input:           none
 *
 * Output:          unsigned char count of the data
 *
 * Side Effects:
 *
 * Overview:        This function returns the number of bytes waiting
 *                  in the receive buffer.
 *
 * Note:
 ********************************************************************/
//lifeng 2022-08
 unsigned char CANGetRxCnt(void)
{
     unsigned char count;

    // Read out of the selected message buffer
    if (_msgRxBuf == 0)
    {
        count = (unsigned char)(CAN1->sFIFOMailBox[0].RDTR&0x0000000f);
    }
    else //if (_msgRxBuf == 1)
    {
        count = (unsigned char)(CAN1->sFIFOMailBox[1].RDTR&0x0000000f);
    }

    return (count);
}



/*********************************************************************
 * Function:        unsigned char *  CANGetRxDataPtr(void)
 *
 * PreCondition:    Data should have been received prior to calling
 *                  this function; otherwise, it is likely the returned
 *                  pointer is either not valid or associated to the
 *                  previous message. Use CANIsRxRdy() to determine if
 *                  data is available.
 *
 * Input:           none
 *
 * Output:          unsigned char *
 *
 * Side Effects:
 *
 * Overview:        This function returns the pointer to the RX buffer.
 *
 * Note:            Use the direct block copy methods for faster data
 *                  movement.
 ********************************************************************/
//lifeng 2022-08   因数据排列顺序可能不同 ，与此函数关联的程序须修改
/*unsigned char *  CANGetRxDataPtr(void)
{
    // Read out of the selected message buffer
    if (_msgRxBuf == 0)
    {
        return (unsigned char *)(&CAN1->sFIFOMailBox[0].RDLR);
    }
    else //if (_msgRxBuf == 1)
    {
        return (unsigned char *)(&CAN1->sFIFOMailBox[1].RDLR);
    }
}*/

//不使用以上函数，32位上有问题
//2022-09 lifeng 用以下函数替换
//一并修改相关文件
unsigned char CANGetRxDataSIG(int dno)      //返回data中的指定位置（dno）的数据，只前4字节内
{
    unli_l_c lc1;

    if (_msgRxBuf == 0){
        lc1.b=CAN1->sFIFOMailBox[0].RDLR;
    }
    else{
        lc1.b=CAN1->sFIFOMailBox[1].RDLR;
    }

    return lc1.c[dno];
}


/*********************************************************************
 * Function:        void CANGetRxDataTyp0(unsigned char *  usrBuf)
 *                  void CANGetRxDataTyp1(unsigned char *  usrBuf)
 *                  void CANGetRxDataTyp2(unsigned char *  usrBuf)
 *
 * PreCondition:    Data should have been received prior to calling
 *                  this function; otherwise, it is likely the returned
 *                  count is either not valid or associated to the
 *                  previous message. Use CANIsRxRdy() to determine if
 *                  data is available.
 *
 * Input:           pointer to user supplied buffer
 *
 * Output:          void
 *
 * Side Effects:
 *
 * Overview:        Get block data from the buffer.
 *
 * Note:            These functions copy blocks of data rather than
 *                  single bytes. This method is very fast; however,
 *                  data limits are not checked. It is up to the
 *                  caller to verify the count to toss data that is
 *                  not valid.
 ********************************************************************/
//lifeng 2022-08
void CANGetRxDataTyp0(unsigned char *  usrBuf)
{
    unli_l_c lc1;
    // Read out of the selected message buffer
    if (_msgRxBuf == 0)
    {
        lc1.b=CAN1->sFIFOMailBox[0].RDLR;
        *usrBuf=lc1.c[0];usrBuf++;
        *usrBuf=lc1.c[1];usrBuf++;
        *usrBuf=lc1.c[2];usrBuf++;
        *usrBuf=lc1.c[3];usrBuf++;
        lc1.b=CAN1->sFIFOMailBox[0].RDHR;
        *usrBuf=lc1.c[0];usrBuf++;
        *usrBuf=lc1.c[1];usrBuf++;
        *usrBuf=lc1.c[2];usrBuf++;
        *usrBuf=lc1.c[3];
    }
    else //if (_msgRxBuf == 1)
    {
        lc1.b=CAN1->sFIFOMailBox[1].RDLR;
        *usrBuf=lc1.c[0];usrBuf++;
        *usrBuf=lc1.c[1];usrBuf++;
        *usrBuf=lc1.c[2];usrBuf++;
        *usrBuf=lc1.c[3];usrBuf++;
        lc1.b=CAN1->sFIFOMailBox[1].RDHR;
        *usrBuf=lc1.c[0];usrBuf++;
        *usrBuf=lc1.c[1];usrBuf++;
        *usrBuf=lc1.c[2];usrBuf++;
        *usrBuf=lc1.c[3];
    }
}

void CANGetRxDataTyp1(unsigned char *  usrBuf)
{
    unli_l_c lc1;
    // Read out of the selected message buffer
    if (_msgRxBuf == 0)
    {
        lc1.b=CAN1->sFIFOMailBox[0].RDLR;
        *usrBuf=lc1.c[1];usrBuf++;
        *usrBuf=lc1.c[2];usrBuf++;
        *usrBuf=lc1.c[3];usrBuf++;
        lc1.b=CAN1->sFIFOMailBox[0].RDHR;
        *usrBuf=lc1.c[0];usrBuf++;
        *usrBuf=lc1.c[1];usrBuf++;
        *usrBuf=lc1.c[2];usrBuf++;
        *usrBuf=lc1.c[3];
    }
    else //if (_msgRxBuf == 1)
    {
        lc1.b=CAN1->sFIFOMailBox[1].RDLR;
        *usrBuf=lc1.c[1];usrBuf++;
        *usrBuf=lc1.c[2];usrBuf++;
        *usrBuf=lc1.c[3];usrBuf++;
        lc1.b=CAN1->sFIFOMailBox[1].RDHR;
        *usrBuf=lc1.c[0];usrBuf++;
        *usrBuf=lc1.c[1];usrBuf++;
        *usrBuf=lc1.c[2];usrBuf++;
        *usrBuf=lc1.c[3];
    }
}

void CANGetRxDataTyp2(unsigned char *  usrBuf)
{
    unli_l_c lc1;
    // Read out of the selected message buffer
    if (_msgRxBuf == 0)
    {
        lc1.b=CAN1->sFIFOMailBox[0].RDLR;
        *usrBuf=lc1.c[2];usrBuf++;
        *usrBuf=lc1.c[3];usrBuf++;
        lc1.b=CAN1->sFIFOMailBox[0].RDHR;
        *usrBuf=lc1.c[0];usrBuf++;
        *usrBuf=lc1.c[1];usrBuf++;
        *usrBuf=lc1.c[2];usrBuf++;
        *usrBuf=lc1.c[3];
    }
    else //if (_msgRxBuf == 1)
    {
        lc1.b=CAN1->sFIFOMailBox[1].RDLR;
        *usrBuf=lc1.c[2];usrBuf++;
        *usrBuf=lc1.c[3];usrBuf++;
        lc1.b=CAN1->sFIFOMailBox[1].RDHR;
        *usrBuf=lc1.c[0];usrBuf++;
        *usrBuf=lc1.c[1];usrBuf++;
        *usrBuf=lc1.c[2];usrBuf++;
        *usrBuf=lc1.c[3];
    }
}



/*********************************************************************
 * Function:        void CANPutTxCID( unsigned int txCID)
 *
 * PreCondition:    The function CANIsTxRdy() must be called prior
 *                  to using this function; otherwise, the previous
 *                  transmission request may be corrupted.
 *
 * Input:           none
 *
 * Output:          unsigned char *
 *
 * Side Effects:
 *
 * Overview:        Write the CID to the TX buffer.
 *
 * Note:
 ********************************************************************/
//lifeng 2022-08
void CANPutTxCID( unsigned int txCID)
{
     _INT temp;
    unli_l_c lc1;

    //rt_kprintf("txCID:%d\n",txCID);

    temp.word = txCID;
    //rt_kprintf("MSB:%d LSB:%d\n",temp.bytes.MSB,temp.bytes.LSB);
    lc1.c[3]=temp.bytes.MSB;
    lc1.c[2]=temp.bytes.LSB&0xe0;
    lc1.c[1]=0;
    lc1.c[0]=0;

    //rt_kprintf("MSB:%d LSB:%d  lc1b:%d\n",temp.bytes.MSB,temp.bytes.LSB,lc1.b);

    CAN1->sTxMailBox[0].TIR=lc1.b;
}



/*********************************************************************
 * Function:        void CANPutTxCnt( unsigned char txCount)
 *
 * PreCondition:    The function CANIsTxRdy() must be called prior
 *                  to using this function; otherwise, the previous
 *                  transmission request may be corrupted.
 *
 * Input:           none
 *
 * Output:          unsigned char *
 *
 * Side Effects:
 *
 * Overview:        Write the count to the TX buffer.
 *
 *
 * Note:
 ********************************************************************/
//lifeng 2022-08
void CANPutTxCnt( unsigned char txCount)
{
    CAN1->sTxMailBox[0].TDTR=0x0000000f&(unsigned long)txCount;
}


/*********************************************************************
 * Function:        unsigned char *  CANGetTxDataPtr(void)
 *
 * PreCondition:    The function CANIsTxRdy() must be called prior
 *                  to using this function; otherwise, the pointer
 *                  may be invalid.
 *
 * Input:           none
 *
 * Output:          unsigned char *
 *
 * Side Effects:
 *
 * Overview:        Return a pointer to the buffer.
 *
 *
 * Note:
 ********************************************************************/
//lifeng 2022-08   改为操作缓冲区
unsigned char *  CANGetTxDataPtr(void)
{
    return &txLFbuf.c[0];
}


/*********************************************************************
 * Function:        void CANPutTxDataTyp0(unsigned char *  usrBuf)
 *                  void CANPutTxDataTyp1(unsigned char *  usrBuf)
 *                  void CANPutTxDataTyp2(unsigned char *  usrBuf)
 *
 * PreCondition:    The function CANIsTxRdy() must be called prior
 *                  to using this function; otherwise, the previous
 *                  transmission request may be corrupted.
 *
 * Input:           none
 *
 * Output:          unsigned char *
 *
 * Side Effects:
 *
 * Overview:        Put a block of data in the TX buffer.
 *
 * Note:            Copying a block into the buffer does not imply
 *                  that the entire block must be transmitted. This
 *                  function mearly loads the data into the buffer
 *                  following the specified format TYP0, TYP1, or TYP2.
 ********************************************************************/
//lifeng 2022-08
void CANPutTxDataTyp0(unsigned char *  usrBuf)
{
    txLFbuf.c[0]=*usrBuf;usrBuf++;
    txLFbuf.c[1]=*usrBuf;usrBuf++;
    txLFbuf.c[2]=*usrBuf;usrBuf++;
    txLFbuf.c[3]=*usrBuf;usrBuf++;
    txLFbuf.c[4]=*usrBuf;usrBuf++;
    txLFbuf.c[5]=*usrBuf;usrBuf++;
    txLFbuf.c[6]=*usrBuf;usrBuf++;
    txLFbuf.c[7]=*usrBuf;
}

void CANPutTxDataTyp1(unsigned char *  usrBuf)
{
    txLFbuf.c[1]=*usrBuf;usrBuf++;
    txLFbuf.c[2]=*usrBuf;usrBuf++;
    txLFbuf.c[3]=*usrBuf;usrBuf++;
    txLFbuf.c[4]=*usrBuf;usrBuf++;
    txLFbuf.c[5]=*usrBuf;usrBuf++;
    txLFbuf.c[6]=*usrBuf;usrBuf++;
    txLFbuf.c[7]=*usrBuf;
}

void CANPutTxDataTyp2(unsigned char *  usrBuf)
{
    txLFbuf.c[2]=*usrBuf;usrBuf++;
    txLFbuf.c[3]=*usrBuf;usrBuf++;
    txLFbuf.c[4]=*usrBuf;usrBuf++;
    txLFbuf.c[5]=*usrBuf;usrBuf++;
    txLFbuf.c[6]=*usrBuf;usrBuf++;
    txLFbuf.c[7]=*usrBuf;
}



/*********************************************************************
 * Function:        void CANInit(void)
 *
 * PreCondition:
 *
 * Input:           none
 *
 * Output:          unsigned char *
 *
 * Side Effects:    Filters are removed.
 *
 * Overview:        Initialize the module.
 *
 * Note:
 ********************************************************************/
//lifeng 2022-08
//IO 和 时钟 相关配置使用 stm32CUBEMX生成的相关函数来完成
//初始化时应在此函数前先调用MX_CAN_Init
//初始化中应使能自动离线恢复和自动重发，其余禁止，以与PIC18F458一致

void CANInit(void)
{
    CANClose();

    // Init some internal control registers
    _msgTxTag = 0;
    _msgRxBuf = 0;

    // Init device specific hardware for CAN

    CAN1->IER=0x00000000;           //不使用CAN中断

    CAN1->FMR|=0x00000001;           //过滤配置模式
    CAN1->FM1R&=0xffffc000;          //所有掩码模式

    CAN1->FS1R|=0x00003fff;          //所有32位宽

    CAN1->FFA1R&=0xffffc000;
    CAN1->FFA1R|=0x00003ffc;         //0,1关联FIFO0  其它关联FIFO1

    CAN1->FA1R&=0xffffc000;          //禁止所有filter

    CAN1->FMR&=0xfffffffe;           //关闭过滤配置模式

}

